package servlet;

import org.apache.commons.io.IOUtils;
import sun.misc.BASE64Encoder;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class FileDownLoadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        //1.准备要下载的文件(假定文件是公共资源)
        //重要：一定保证当tomcat启动后，在工作目录(out)下有download文件夹并且有可供下载的文件

        //2.获取到要下载的文件的名字
        String downLoadName = req.getParameter("name");

        //3.给http响应设置响应头 Content-Type 就是文件的MIME类型
        //  通过servletContext获取
        ServletContext servletContext = req.getServletContext();
        String downLoadPath = "/download/";
        String downLoadFullPath = downLoadPath + downLoadName;
        String mimeType = servletContext.getMimeType(downLoadFullPath);
        resp.setContentType(mimeType);

        //4.给http响应设置响应头
        /*
            I)火狐中文编码是base64
            II)Content-Disposition 指下载的数据的展示形式:attachment;表示以文件下载的方式
            III)ie/chrome中文编码是URL编码
         */
        if (req.getHeader("User-Agent").contains("Firefox")) {
            // 火狐 Base64编码
            resp.setHeader("Content-Disposition", "attachment; filename==?UTF-8?B?" +
                    new BASE64Encoder().encode(downLoadName.getBytes(StandardCharsets.UTF_8)) + "?=");
        } else {
            // 其他(主流ie/chrome)使用URL编码操作
            resp.setHeader("Content-Disposition", "attachment; filename=" +
                    URLEncoder.encode(downLoadName, "UTF-8"));
        }

        //5.读取下载的文件数据，返回给客户端/浏览器
        /*
            I)先创建一个和要下载的文件关联的输入流
            II)得到要返回数据的输出流，因为返回的文件大多数是二进制流，所以使用字节流
            III)使用工具类，将输入流关联的文件，拷贝到输出流并返回到浏览器
         */
        InputStream resourceAsStream
                = servletContext.getResourceAsStream(downLoadFullPath);
        ServletOutputStream outputStream = resp.getOutputStream();
        IOUtils.copy(resourceAsStream, outputStream);
    }
}
